#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
配置文件管理
提供配置文件的读取、保存和验证功能
"""

import os
import json
from pathlib import Path
from typing import Dict, Any, Optional

class ConfigManager:
    """配置管理器"""
    
    def __init__(self, config_dir: Optional[str] = None):
        """
        初始化配置管理器
        
        Args:
            config_dir: 配置目录路径，默认为用户目录下的.yolo_dataset_tool
        """
        if config_dir is None:
            config_dir = os.path.expanduser("~/.yolo_dataset_tool")
        
        self.config_dir = Path(config_dir)
        self.config_file = self.config_dir / "config.json"
        self.image_search_config_file = self.config_dir / "image_search_config.json"
        self.download_config_file = self.config_dir / "download_config.json"
        
        # 确保配置目录存在
        self.config_dir.mkdir(parents=True, exist_ok=True)
        
        # 默认配置
        self.default_config = self._get_default_config()
        
    def _get_default_config(self) -> Dict[str, Any]:
        """获取默认配置"""
        return {
            "app_info": {
                "name": "YOLO数据集获取工具",
                "version": "1.0.0",
                "author": "YOLO Dataset Tool Team"
            },
            "ui_settings": {
                "window_width": 1200,
                "window_height": 800,
                "sidebar_width": 300,
                "theme": "default",
                "language": "zh_CN",
                "remember_window_state": True
            },
            "download_settings": {
                "save_directory": os.path.expanduser("~/Downloads"),
                "max_file_size": 1024,  # MB
                "timeout": 300,  # 秒
                "retry_count": 3,
                "chunk_size": 8,  # KB
                "auto_rename": True,
                "create_subfolders": True,
                "verify_checksum": False
            },
            "image_search_settings": {
                "max_images_per_page": 50,
                "image_quality": "medium",  # low, medium, high
                "download_format": "original",  # original, jpg, png
                "waterfall_columns": 4,
                "max_pages": 100,
                "pagination_buttons": 5,
                "auto_load_more": False,
                "cache_images": True,
                "cache_size": 100  # MB
            },
            "search_engines": {
                "google_images": {
                    "enabled": True,
                    "api_key": "",
                    "custom_id": ""
                },
                "bing_images": {
                    "enabled": True,
                    "api_key": "",
                    "endpoint": "https://api.bing.microsoft.com/v7.0/images/search"
                },
                "unsplash": {
                    "enabled": True,
                    "access_key": "",
                    "secret_key": ""
                },
                "pexels": {
                    "enabled": True,
                    "api_key": ""
                },
                "pixabay": {
                    "enabled": True,
                    "api_key": ""
                }
            },
            "dataset_sites": {
                "coco": {
                    "name": "COCO",
                    "url": "https://cocodataset.org/",
                    "description": "Common Objects in Context",
                    "enabled": True
                },
                "imagenet": {
                    "name": "ImageNet",
                    "url": "https://www.image-net.org/",
                    "description": "大规模图像数据库",
                    "enabled": True
                },
                "open_images": {
                    "name": "Open Images",
                    "url": "https://storage.googleapis.com/openimages/web/index.html",
                    "description": "Google开源图像数据集",
                    "enabled": True
                },
                "pascal_voc": {
                    "name": "Pascal VOC",
                    "url": "http://host.robots.ox.ac.uk/pascal/VOC/",
                    "description": "Pascal Visual Object Classes",
                    "enabled": True
                },
                "yolo_dataset": {
                    "name": "YOLO Dataset",
                    "url": "https://github.com/ultralytics/yolov5",
                    "description": "YOLO官方数据集",
                    "enabled": True
                },
                "roboflow": {
                    "name": "Roboflow",
                    "url": "https://roboflow.com/",
                    "description": "计算机视觉数据集平台",
                    "enabled": True
                },
                "kaggle": {
                    "name": "Kaggle",
                    "url": "https://www.kaggle.com/datasets",
                    "description": "数据科学竞赛平台",
                    "enabled": True
                },
                "papers_with_code": {
                    "name": "Papers With Code",
                    "url": "https://paperswithcode.com/datasets",
                    "description": "学术论文相关数据集",
                    "enabled": True
                }
            },
            "image_search_sites": {
                "google_images": {
                    "name": "Google Images",
                    "url": "https://www.google.com/images",
                    "description": "Google图片搜索",
                    "enabled": True
                },
                "bing_images": {
                    "name": "Bing Images",
                    "url": "https://www.bing.com/images",
                    "description": "必应图片搜索",
                    "enabled": True
                },
                "baidu_images": {
                    "name": "百度图片",
                    "url": "https://image.baidu.com/",
                    "description": "百度图片搜索",
                    "enabled": True
                },
                "unsplash": {
                    "name": "Unsplash",
                    "url": "https://unsplash.com/",
                    "description": "高质量免费图片",
                    "enabled": True
                },
                "pexels": {
                    "name": "Pexels",
                    "url": "https://www.pexels.com/",
                    "description": "免费商用图片",
                    "enabled": True
                },
                "pixabay": {
                    "name": "Pixabay",
                    "url": "https://pixabay.com/",
                    "description": "免费图片素材",
                    "enabled": True
                },
                "flickr": {
                    "name": "Flickr",
                    "url": "https://www.flickr.com/",
                    "description": "图片分享平台",
                    "enabled": True
                },
                "getty_images": {
                    "name": "Getty Images",
                    "url": "https://www.gettyimages.com/",
                    "description": "专业图片库",
                    "enabled": True
                }
            },
            "advanced_settings": {
                "debug_mode": False,
                "log_level": "INFO",  # DEBUG, INFO, WARNING, ERROR
                "max_log_size": 10,  # MB
                "log_retention_days": 30,
                "auto_update_check": True,
                "update_channel": "stable"  # stable, beta, dev
            }
        }
    
    def load_config(self) -> Dict[str, Any]:
        """加载配置文件"""
        if self.config_file.exists():
            try:
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                
                # 合并默认配置（确保新配置项被添加）
                merged_config = self._merge_configs(self.default_config, config)
                return merged_config
                
            except Exception as e:
                print(f"加载配置文件失败: {e}")
                return self.default_config.copy()
        else:
            # 创建默认配置文件
            self.save_config(self.default_config)
            return self.default_config.copy()
    
    def save_config(self, config: Dict[str, Any]) -> bool:
        """保存配置文件"""
        try:
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, indent=2, ensure_ascii=False)
            return True
        except Exception as e:
            print(f"保存配置文件失败: {e}")
            return False
    
    def _merge_configs(self, default: Dict[str, Any], user: Dict[str, Any]) -> Dict[str, Any]:
        """合并配置（递归合并字典）"""
        result = default.copy()
        
        for key, value in user.items():
            if key in result and isinstance(result[key], dict) and isinstance(value, dict):
                result[key] = self._merge_configs(result[key], value)
            else:
                result[key] = value
                
        return result
    
    def get(self, key: str, default: Any = None) -> Any:
        """获取配置值（支持点号分隔的键）"""
        config = self.load_config()
        keys = key.split('.')
        value = config
        
        try:
            for k in keys:
                value = value[k]
            return value
        except (KeyError, TypeError):
            return default
    
    def set(self, key: str, value: Any) -> bool:
        """设置配置值（支持点号分隔的键）"""
        config = self.load_config()
        keys = key.split('.')
        
        # 导航到目标位置
        current = config
        for k in keys[:-1]:
            if k not in current:
                current[k] = {}
            current = current[k]
        
        # 设置值
        current[keys[-1]] = value
        
        return self.save_config(config)
    
    def reset_to_default(self) -> bool:
        """重置为默认配置"""
        return self.save_config(self.default_config)
    
    def validate_config(self, config: Dict[str, Any]) -> tuple:
        """验证配置"""
        errors = []
        
        # 验证UI设置
        ui_settings = config.get('ui_settings', {})
        if not isinstance(ui_settings.get('window_width'), int) or ui_settings['window_width'] < 800:
            errors.append("窗口宽度必须是大于等于800的整数")
        
        if not isinstance(ui_settings.get('window_height'), int) or ui_settings['window_height'] < 600:
            errors.append("窗口高度必须是大于等于600的整数")
        
        # 验证下载设置
        download_settings = config.get('download_settings', {})
        if not isinstance(download_settings.get('max_file_size'), (int, float)) or download_settings['max_file_size'] <= 0:
            errors.append("最大文件大小必须是正数")
        
        if not isinstance(download_settings.get('timeout'), int) or download_settings['timeout'] <= 0:
            errors.append("超时时间必须是正整数")
        
        # 验证图片搜索设置
        image_search_settings = config.get('image_search_settings', {})
        if not isinstance(image_search_settings.get('max_images_per_page'), int) or not (1 <= image_search_settings['max_images_per_page'] <= 100):
            errors.append("每页最大图片数量必须在1-100之间")
        
        return len(errors) == 0, errors
    
    def export_config(self, file_path: str) -> bool:
        """导出配置到文件"""
        try:
            config = self.load_config()
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(config, f, indent=2, ensure_ascii=False)
            return True
        except Exception as e:
            print(f"导出配置失败: {e}")
            return False
    
    def import_config(self, file_path: str) -> bool:
        """从文件导入配置"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                config = json.load(f)
            
            # 验证配置
            is_valid, errors = self.validate_config(config)
            if not is_valid:
                print(f"配置验证失败: {', '.join(errors)}")
                return False
            
            return self.save_config(config)
        except Exception as e:
            print(f"导入配置失败: {e}")
            return False
    
    def get_config_info(self) -> Dict[str, Any]:
        """获取配置信息"""
        return {
            'config_file': str(self.config_file),
            'config_dir': str(self.config_dir),
            'file_exists': self.config_file.exists(),
            'file_size': self.config_file.stat().st_size if self.config_file.exists() else 0,
            'last_modified': self.config_file.stat().st_mtime if self.config_file.exists() else 0
        }

# 全局配置管理器实例
config_manager = ConfigManager()

def get_config(key: str = None, default: Any = None) -> Any:
    """获取配置的便捷函数"""
    if key is None:
        return config_manager.load_config()
    return config_manager.get(key, default)

def set_config(key: str, value: Any) -> bool:
    """设置配置的便捷函数"""
    return config_manager.set(key, value)

def save_config(config: Dict[str, Any] = None) -> bool:
    """保存配置的便捷函数"""
    if config is None:
        config = config_manager.load_config()
    return config_manager.save_config(config)

if __name__ == "__main__":
    # 测试配置管理器
    print("配置管理器测试")
    print("=" * 50)
    
    # 加载配置
    config = get_config()
    print(f"应用名称: {config['app_info']['name']}")
    print(f"版本: {config['app_info']['version']}")
    
    # 获取特定配置
    window_width = get_config('ui_settings.window_width')
    print(f"窗口宽度: {window_width}")
    
    # 设置配置
    set_config('ui_settings.window_width', 1400)
    print(f"新的窗口宽度: {get_config('ui_settings.window_width')}")
    
    # 验证配置
    is_valid, errors = config_manager.validate_config(config)
    print(f"配置验证: {'通过' if is_valid else '失败'}")
    if errors:
        print(f"错误: {', '.join(errors)}")
    
    # 配置信息
    info = config_manager.get_config_info()
    print(f"配置文件: {info['config_file']}")
    print(f"文件存在: {info['file_exists']}")
